/**
 * @author Zvonimir Fras <zvonimir@frasbros.com>
 */

#ifndef NEURALNETWORK_H
#define NEURALNETWORK_H

#include <QFile>
#include <QStringList>

#include "neuron.h"

class NeuralNetwork : public QObject
{
   public:
      NeuralNetwork( QObject *parent = 0 );
      
      /**
      * @return
      *  0 on success
      * -1 on filemanagement error
      * -2 on corrupted format
      */
      int load( const QString &filename );
      
      /**
      * @return
      *  0 on success
      *  1 on file exists (if overwrite == false )
      * -1 on filemanagement error
      */
      int save( const QString &filename, bool overwrite = true );
      
      void clear();
      
      void random( const QList< int > &structure );
      
      /**
      * @return
      * QList< float > containing output values on success
      * empty list on error
      */
      QList< float > output( const QList< float > &input );
      
      /**
      * @return
      * Synapse* pointer to a Synapse at index i
      * NULL on index out of range
      */
      Synapse *synapseByIndex( int i ) const;
      
      /**
      * @return
      * int number of synapses in network
      */
      int synapseCount() const;
      
      /**
      * @return
      *  0 on success
      * -1 on error
      */
      int backpropagate( const QList< float > &output, const QList< float > &target );
      int backpropagate( const QList< float > &error );
      
      /**
      * @return
      * totalError on success (najmanji kvadrat)
      * -1 on error
      */
      float totalError();
      
      
      NeuralNetwork( const NeuralNetwork &ann );
      NeuralNetwork &operator=( const NeuralNetwork &ann );
      
      /**
      * @return
      * output and input size respectivly
      */
      int outputSize();
      int inputSize();
      
      void setLearningRate( float lr );
      float learningRate();
      
      
      void updateSynapseList();
      
      QList< int > networkStructure();
      
   private:
      QFile m_tmpFile;
      QObject *m_networkParent; // delete this to delete network
      QList< QList< Neuron * > > m_layers; // every layer has a list of neurons
      QList< Synapse* > m_synapseList;
      float m_learningRate;
      
      QString m_readNextLine(); // returns empty string on error
};

#endif // NEURALNETWORK_H
